package com.pro.common.file.storage.service;

import com.pro.common.api.exception.BusinessException;
import com.pro.common.api.statics.user.file.storage.enums.EnumFileStoragePlatform;
import com.pro.common.api.statics.user.file.storage.model.dto.IFileStorageProperties;
import com.pro.common.api.statics.user.file.storage.model.dto.IFileStoragePropertiesContainer;
import com.pro.common.api.statics.user.file.storage.service.IFileStorageService;
import com.pro.common.file.storage.dto.ClientAndProps;
import com.pro.framework.api.util.StrUtils;
import jakarta.annotation.PreDestroy;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public abstract class AbstractFileStorageService<C, PL extends IFileStoragePropertiesContainer<P>, P extends IFileStorageProperties> implements IFileStorageService {

    /**
     * 各 bucket 对应的客户端缓存
     */
    private final Map<String, ClientAndProps<C, P>> clientMap = new ConcurrentHashMap<>();

    public abstract PL getPropertiesList();

    /**
     * 平台类型（由子类指定，例如 HUAWEI_OBS）
     */
    protected abstract EnumFileStoragePlatform getPlatform();

    /**
     * 创建具体厂商的 Client
     */
    protected abstract C createClient(P cfg);

    /**
     * 获取客户端（懒加载）
     */
    protected ClientAndProps<C, P> getClientAndProps(String bucket) {
        if (bucket == null || bucket.isEmpty()) {
            throw new BusinessException("Bucket " + bucket + " does not exist");
        }
        return clientMap.computeIfAbsent(bucket, this::createClientByBucket);
    }

    /**
     * 从配置中获取并创建 Client
     */
    private ClientAndProps<C, P> createClientByBucket(String bucket) {
        for (P property : getPropertiesList().getProperties()) {
            if (property.getBucket().equals(bucket)) {
                return new ClientAndProps<>(createClient(property), property);
            }
        }
        throw new BusinessException("Bucket " + bucket + " does not exist");
    }

    /**
     * 刷新（重新创建）指定 bucket 的客户端
     */
    public void refreshClient(String bucket) {
        clientMap.compute(bucket, (b, dto) -> {
            if (dto != null) {
                C client = dto.getClient();
                closeClientQuietly(client);
            }
            return createClientByBucket(b);
        });
    }

    /**
     * 关闭所有客户端
     */
    @PreDestroy
    public void destroy() {
        clientMap.values().stream().map(ClientAndProps::getClient).forEach(this::closeClientQuietly);
    }

    /**
     * 子类可选择覆盖：关闭客户端连接
     */
    protected void closeClientQuietly(C client) {
        // 默认空实现
    }
}
